package handlers

import (
	"restaurant-system/config"
	"restaurant-system/internal/models"
	"time"

	"github.com/gin-gonic/gin"
)

type CreateCouponTemplateRequest struct {
	Name        string    `json:"name" binding:"required"`
	Type        string    `json:"type" binding:"required,oneof=amount percent"`
	Value       float64   `json:"value" binding:"required,gt=0"`
	MinAmount   float64   `json:"min_amount" binding:"required,gte=0"`
	ValidDays   int       `json:"valid_days" binding:"required,gt=0"`
	StartTime   time.Time `json:"start_time" binding:"required"`
	EndTime     time.Time `json:"end_time" binding:"required,gtfield=StartTime"`
	TotalCount  int       `json:"total_count" binding:"required,gt=0"`
	Description string    `json:"description"`
}

// 创建优惠券模板
func CreateCouponTemplate(c *gin.Context) {
	var req CreateCouponTemplateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	template := models.CouponTemplate{
		Name:        req.Name,
		Type:        req.Type,
		Value:       req.Value,
		MinAmount:   req.MinAmount,
		ValidDays:   req.ValidDays,
		StartTime:   req.StartTime,
		EndTime:     req.EndTime,
		TotalCount:  req.TotalCount,
		Description: req.Description,
	}

	if err := config.DB.Create(&template).Error; err != nil {
		c.JSON(500, gin.H{"error": "创建优惠券模板失败"})
		return
	}

	c.JSON(200, gin.H{"message": "创建优惠券模板成功", "template": template})
}

// 发放优惠券给用户
func IssueCoupon(c *gin.Context) {
	var req struct {
		UserID     uint `json:"user_id" binding:"required"`
		TemplateID uint `json:"template_id" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	// 检查用户是否存在
	var user models.User
	if err := config.DB.First(&user, req.UserID).Error; err != nil {
		c.JSON(404, gin.H{"error": "用户不存在"})
		return
	}

	// 检查优惠券模板是否存在且有效
	var template models.CouponTemplate
	if err := config.DB.First(&template, req.TemplateID).Error; err != nil {
		c.JSON(404, gin.H{"error": "优惠券模板不存在"})
		return
	}

	now := time.Now()
	if now.Before(template.StartTime) || now.After(template.EndTime) {
		c.JSON(400, gin.H{"error": "优惠券发放时间无效"})
		return
	}

	if template.UsedCount >= template.TotalCount {
		c.JSON(400, gin.H{"error": "优惠券已发完"})
		return
	}

	// 创建用户优惠券
	userCoupon := models.UserCoupon{
		UserID:     req.UserID,
		TemplateID: req.TemplateID,
		Status:     "unused",
		ValidUntil: now.AddDate(0, 0, template.ValidDays),
	}

	if err := config.DB.Create(&userCoupon).Error; err != nil {
		c.JSON(500, gin.H{"error": "发放优惠券失败"})
		return
	}

	// 更新优惠券模板使用数量
	if err := config.DB.Model(&template).Update("used_count", template.UsedCount+1).Error; err != nil {
		c.JSON(500, gin.H{"error": "更新优惠券使用数量失败"})
		return
	}

	c.JSON(200, gin.H{"message": "发放优惠券成功", "coupon": userCoupon})
}

// 获取用户优惠券列表
func GetUserCoupons(c *gin.Context) {
	userID, _ := c.Get("userID")
	var coupons []models.UserCoupon

	if err := config.DB.Preload("Template").Where("user_id = ?", userID).Find(&coupons).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取优惠券列表失败"})
		return
	}

	// 更新过期状态
	now := time.Now()
	for i := range coupons {
		if coupons[i].Status == "unused" && now.After(coupons[i].ValidUntil) {
			coupons[i].Status = "expired"
			config.DB.Save(&coupons[i])
		}
	}

	c.JSON(200, gin.H{"coupons": coupons})
}

// 使用优惠券
func UseCoupon(c *gin.Context) {
	userID, _ := c.Get("userID")
	var req struct {
		CouponID uint    `json:"coupon_id" binding:"required"`
		OrderID  uint    `json:"order_id" binding:"required"`
		Amount   float64 `json:"amount" binding:"required,gt=0"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	// 开启事务
	tx := config.DB.Begin()

	// 获取优惠券信息
	var coupon models.UserCoupon
	if err := tx.Preload("Template").Where("id = ? AND user_id = ?", req.CouponID, userID).First(&coupon).Error; err != nil {
		tx.Rollback()
		c.JSON(404, gin.H{"error": "优惠券不存在"})
		return
	}

	// 检查优惠券状态
	if coupon.Status != "unused" {
		tx.Rollback()
		c.JSON(400, gin.H{"error": "优惠券已使用或已过期"})
		return
	}

	// 检查订单金额是否满足最低使用金额
	if req.Amount < coupon.Template.MinAmount {
		tx.Rollback()
		c.JSON(400, gin.H{"error": "订单金额未达到优惠券使用条件"})
		return
	}

	// 计算优惠金额
	var discountAmount float64
	if coupon.Template.Type == "amount" {
		discountAmount = coupon.Template.Value
	} else {
		discountAmount = req.Amount * (coupon.Template.Value / 100)
	}

	// 更新优惠券状态
	now := time.Now()
	if err := tx.Model(&coupon).Updates(map[string]interface{}{
		"status":        "used",
		"used_time":     now,
		"used_order_id": req.OrderID,
	}).Error; err != nil {
		tx.Rollback()
		c.JSON(500, gin.H{"error": "更新优惠券状态失败"})
		return
	}

	tx.Commit()
	c.JSON(200, gin.H{
		"message":         "使用优惠券成功",
		"discount_amount": discountAmount,
	})
}

// 获取优惠券模板列表
func GetCouponTemplates(c *gin.Context) {
	var templates []models.CouponTemplate

	// 加载优惠券模板列表，按创建时间倒序排序
	if err := config.DB.Order("created_at desc").Find(&templates).Error; err != nil {
		c.JSON(500, gin.H{"error": "获取优惠券模板列表失败"})
		return
	}

	// 对每个模板计算已使用数量
	for i := range templates {
		var usedCount int64
		if err := config.DB.Model(&models.UserCoupon{}).
			Where("template_id = ? AND status = ?", templates[i].ID, "used").
			Count(&usedCount).Error; err != nil {
			c.JSON(500, gin.H{"error": "计算优惠券使用数量失败"})
			return
		}
		templates[i].UsedCount = int(usedCount)
	}

	c.JSON(200, gin.H{"templates": templates})
}

// 用户兑换优惠券
func ExchangeCoupon(c *gin.Context) {
	userID, _ := c.Get("userID")
	var req struct {
		TemplateID uint `json:"template_id" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	// 开启事务
	tx := config.DB.Begin()

	// 获取优惠券模板
	var template models.CouponTemplate
	if err := tx.First(&template, req.TemplateID).Error; err != nil {
		tx.Rollback()
		c.JSON(404, gin.H{"error": "优惠券模板不存在"})
		return
	}

	// 检查优惠券是否在有效期内
	now := time.Now()
	if now.Before(template.StartTime) || now.After(template.EndTime) {
		tx.Rollback()
		c.JSON(400, gin.H{"error": "优惠券不在兑换期内"})
		return
	}

	// 检查优惠券是否已兑完
	if template.UsedCount >= template.TotalCount {
		tx.Rollback()
		c.JSON(400, gin.H{"error": "优惠券已兑换完"})
		return
	}

	// 获取用户积分
	var points models.PointRecord
	if err := tx.Where("user_id = ?", userID).First(&points).Error; err != nil {
		tx.Rollback()
		c.JSON(500, gin.H{"error": "获取用户积分失败"})
		return
	}

	// 检查积分是否足够
	if points.Points < template.PointsNeeded {
		tx.Rollback()
		c.JSON(400, gin.H{"error": "积分不足"})
		return
	}

	// 扣除积分
	if err := tx.Model(&points).Update("balance", points.Points-template.PointsNeeded).Error; err != nil {
		tx.Rollback()
		c.JSON(500, gin.H{"error": "扣除积分失败"})
		return
	}

	// 记录积分使用记录
	pointRecord := models.PointRecord{
		UserID: uint(userID.(float64)),
		Points: -template.PointsNeeded,
		Type:   "use_coupon",
		Remark: "兑换优惠券: " + template.Name,
	}
	if err := tx.Create(&pointRecord).Error; err != nil {
		tx.Rollback()
		c.JSON(500, gin.H{"error": "记录积分使用失败"})
		return
	}

	// 创建用户优惠券
	validUntil := now.AddDate(0, 0, template.ValidDays)
	userCoupon := models.UserCoupon{
		UserID:     uint(userID.(float64)),
		TemplateID: template.ID,
		Status:     "unused",
		ValidUntil: validUntil,
	}

	if err := tx.Create(&userCoupon).Error; err != nil {
		tx.Rollback()
		c.JSON(500, gin.H{"error": "创建优惠券失败"})
		return
	}

	// 更新优惠券模板的已兑换数量
	if err := tx.Model(&template).Update("used_count", template.UsedCount+1).Error; err != nil {
		tx.Rollback()
		c.JSON(500, gin.H{"error": "更新优惠券兑换数量失败"})
		return
	}

	tx.Commit()
	c.JSON(200, gin.H{
		"message": "兑换优惠券成功",
		"coupon":  userCoupon,
	})
}
